package org.jsola.hr.service.impl;

import org.jsola.core.Page;
import org.jsola.hr.common.ExampleKit;
import org.jsola.hr.common.HrLogKit;
import org.jsola.hr.constant.HrConstants;
import org.jsola.hr.dao.IAttendanceMonthlyArchiveDAO;
import org.jsola.hr.dao.IAttendanceMonthlyDAO;
import org.jsola.hr.dto.AttendanceMonthlyAddDTO;
import org.jsola.hr.dto.AttendanceMonthlyArchiveAddDTO;
import org.jsola.hr.dto.AttendanceMonthlyArchiveUpdateDTO;
import org.jsola.hr.entity.AttendanceMonthlyArchiveDO;
import org.jsola.hr.entity.AttendanceMonthlyDO;
import org.jsola.hr.entity.EmpInfoDO;
import org.jsola.hr.query.AttendanceMonthlyArchiveQuery;
import org.jsola.hr.service.IAttendanceMonthlyArchiveService;
import org.jsola.hr.service.IEmpInfoService;
import org.jsola.hr.vo.AttendanceMonthlyArchiveListVO;
import org.jsola.hr.vo.AttendanceMonthlyArchiveVO;
import org.jsola.user.core.TokenUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import tk.mybatis.mapper.entity.Example;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 员工考勤月统计归档
 *
 * @author zhr
 */
@Service("hrAttendanceMonthlyArchiveServiceImpl")
public class AttendanceMonthlyArchiveServiceImpl implements IAttendanceMonthlyArchiveService {

    @Autowired
    private IAttendanceMonthlyArchiveDAO attendanceMonthlyArchiveDAO;

    @Autowired
    private IAttendanceMonthlyDAO attendanceMonthlyDAO;

    @Autowired
    private IEmpInfoService empInfoService;

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public AttendanceMonthlyArchiveVO save(AttendanceMonthlyArchiveAddDTO attendanceMonthlyArchiveAddDTO, TokenUser tokenUser) {
        // 转DO
        AttendanceMonthlyArchiveDO attendanceMonthlyArchiveDO = attendanceMonthlyArchiveAddDTO.to(AttendanceMonthlyArchiveDO.class);
        // 保存
        attendanceMonthlyArchiveDO = save(attendanceMonthlyArchiveDO, tokenUser.getSiteId(), tokenUser.getUserId());
        HrLogKit.logForSave("新增员工考勤月统计归档", "saveAttendanceMonthlyArchive", attendanceMonthlyArchiveDO.getId(), tokenUser);
        return attendanceMonthlyArchiveDO.to(AttendanceMonthlyArchiveVO.class);
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public int update(AttendanceMonthlyArchiveUpdateDTO attendanceMonthlyArchiveUpdateDTO, TokenUser tokenUser) {
        //转DO
        AttendanceMonthlyArchiveDO attendanceMonthlyArchiveDO = attendanceMonthlyArchiveUpdateDTO.to(AttendanceMonthlyArchiveDO.class);
        HrLogKit.logForUpdate("修改员工考勤月统计归档", "updateAttendanceMonthlyArchive", attendanceMonthlyArchiveDO.getId(), tokenUser);
        //根据主键更新，只更新非null值
        return updateByIdSelective(attendanceMonthlyArchiveDO, tokenUser.getSiteId(), tokenUser.getUserId());
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public int deleteByIds(TokenUser tokenUser, String... attendanceMonthlyArchiveIds) {
        HrLogKit.logForDelete("批量删除员工考勤月统计归档", "deleteAttendanceMonthlyArchiveByIds"
                , Arrays.toString(attendanceMonthlyArchiveIds), tokenUser);
        return logicalDeleteByIds(tokenUser.getSiteId(), tokenUser.getUserId(), (Object[]) attendanceMonthlyArchiveIds);
    }


    @Override
    public AttendanceMonthlyArchiveVO selectById(String attendanceMonthlyArchiveId, String siteId) {
        AttendanceMonthlyArchiveDO attendanceMonthlyArchiveDO = selectDOById(attendanceMonthlyArchiveId, siteId);
        if (attendanceMonthlyArchiveDO == null) {
            return null;
        }
        return attendanceMonthlyArchiveDO.to(AttendanceMonthlyArchiveVO.class);
    }

    @Override
    public List<AttendanceMonthlyArchiveListVO> select(AttendanceMonthlyArchiveQuery attendanceMonthlyArchiveQuery, String siteId) {
        List<AttendanceMonthlyArchiveDO> attendanceMonthlyArchiveDOList = selectDO(attendanceMonthlyArchiveQuery, siteId);
        if (CollectionUtils.isEmpty(attendanceMonthlyArchiveDOList)) {
            return attendanceMonthlyArchiveDOList == null ? null : new ArrayList<>();
        }
        return attendanceMonthlyArchiveDOList.stream()
                .map(attendanceMonthlyArchiveDO -> attendanceMonthlyArchiveDO.to(AttendanceMonthlyArchiveListVO.class))
                .collect(Collectors.toList());
    }

    @Override
    public int selectCount(AttendanceMonthlyArchiveQuery attendanceMonthlyArchiveQuery, String siteId) {
        Example example = buildExample(attendanceMonthlyArchiveQuery, siteId);
        return attendanceMonthlyArchiveDAO.selectCountByExample(example);
    }

    @Override
    public Page<AttendanceMonthlyArchiveListVO> selectPage(AttendanceMonthlyArchiveQuery attendanceMonthlyArchiveQuery, String siteId) {
        Example example = buildExample(attendanceMonthlyArchiveQuery, siteId);
        Page<AttendanceMonthlyArchiveDO> page = attendanceMonthlyArchiveDAO.selectPageByExample(example,
                attendanceMonthlyArchiveQuery.getPageNo(),
                attendanceMonthlyArchiveQuery.getPageSize());

        return page.to(AttendanceMonthlyArchiveListVO.class);
    }

    @Override
    public AttendanceMonthlyArchiveDO selectDOById(String attendanceMonthlyArchiveId, String siteId) {
        return listById(attendanceMonthlyArchiveId, siteId);
    }

    @Override
    public List<AttendanceMonthlyArchiveDO> selectDO(AttendanceMonthlyArchiveQuery attendanceMonthlyArchiveQuery, String siteId) {
        Example example = buildExample(attendanceMonthlyArchiveQuery, siteId);
        return attendanceMonthlyArchiveDAO.selectByExample(example);
    }


    /**
     * 根据查询参数，构建example
     *
     * @param attendanceMonthlyArchiveQuery 查询参数
     * @param siteId                        所属站点id
     * @return example
     */
    private Example buildExample(AttendanceMonthlyArchiveQuery attendanceMonthlyArchiveQuery, String siteId) {
        Example example = new Example(AttendanceMonthlyArchiveDO.class);
        example.and()
                .andEqualTo("valid", true)
                .andEqualTo("siteId", siteId);
        if (attendanceMonthlyArchiveQuery.getCompanyId() != null) {
            example.and().andEqualTo("companyId", attendanceMonthlyArchiveQuery.getCompanyId());
        }
        if (attendanceMonthlyArchiveQuery.getYear() != null) {
            example.and().andEqualTo("year", attendanceMonthlyArchiveQuery.getYear());
        }
        if (attendanceMonthlyArchiveQuery.getMonth() != null) {
            example.and().andEqualTo("month", attendanceMonthlyArchiveQuery.getMonth());
        }
        if (attendanceMonthlyArchiveQuery.getEmpCost() != null) {
            example.and().andEqualTo("empCost", attendanceMonthlyArchiveQuery.getEmpCost());
        }
        if (attendanceMonthlyArchiveQuery.getEmpTaxBefore() != null) {
            example.and().andEqualTo("empTaxBefore", attendanceMonthlyArchiveQuery.getEmpTaxBefore());
        }
        if (attendanceMonthlyArchiveQuery.getEmpSocPf() != null) {
            example.and().andEqualTo("empSocPf", attendanceMonthlyArchiveQuery.getEmpSocPf());
        }
        if (attendanceMonthlyArchiveQuery.getStatus() != null) {
            example.and().andEqualTo("status", attendanceMonthlyArchiveQuery.getStatus());
        }
        if (attendanceMonthlyArchiveQuery.getRemark() != null) {
            example.and().andEqualTo("remark", attendanceMonthlyArchiveQuery.getRemark());
        }
        // 排序
        ExampleKit.setExampleOrder(example, attendanceMonthlyArchiveQuery.getOrders());
        return example;
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public AttendanceMonthlyArchiveVO generateArchive(AttendanceMonthlyAddDTO attendanceMonthlyAddDTO, TokenUser tokenUser) {
        //删除相同年月归档记录
        AttendanceMonthlyArchiveDO attendanceMonthlyArchiveDO = new AttendanceMonthlyArchiveDO();
        attendanceMonthlyArchiveDO.setYear(attendanceMonthlyAddDTO.getYear());
        attendanceMonthlyArchiveDO.setMonth(attendanceMonthlyAddDTO.getMonth());
        attendanceMonthlyArchiveDO.setCompanyId(attendanceMonthlyAddDTO.getCompanyId());
        attendanceMonthlyArchiveDO.setSiteId(tokenUser.getSiteId());
        attendanceMonthlyArchiveDAO.delete(attendanceMonthlyArchiveDO);

        //按年月查询归档记录
        Example example = new Example(AttendanceMonthlyDO.class);
        example.and()
                .andEqualTo("companyId", attendanceMonthlyAddDTO.getCompanyId())
                .andEqualTo("year", attendanceMonthlyAddDTO.getYear())
                .andEqualTo("month", attendanceMonthlyAddDTO.getMonth())
                .andEqualTo("valid", true)
                .andEqualTo("siteId", tokenUser.getSiteId());
        List<AttendanceMonthlyDO> attendanceMonthlyDOList = attendanceMonthlyDAO.selectByExample(example);
        //查询员工薪资相关信息
        EmpInfoDO empInfoDO = new EmpInfoDO();
        empInfoDO.setValid(true);
        empInfoDO.setCompanyId(attendanceMonthlyAddDTO.getCompanyId());
        List<EmpInfoDO> empInfoDOList = empInfoService.listWithSalary(empInfoDO, tokenUser.getSiteId());

        //税前工资
        Long taxBefore = 0L;
        if (!CollectionUtils.isEmpty(empInfoDOList)) {
            taxBefore = Long.valueOf(empInfoDOList.stream().map(EmpInfoDO::getSalaryBasic).reduce(0, Integer::sum));
        }

        //人工成本（税前工资 + 五险一金 + 团队提成 + 业务佣金 + 加班费 + 补贴）
        Integer sumSocDed = attendanceMonthlyDOList.stream().map(AttendanceMonthlyDO::getSocDed).reduce(0, Integer::sum);
        Integer sumPfDed = attendanceMonthlyDOList.stream().map(AttendanceMonthlyDO::getPfDed).reduce(0, Integer::sum);
        Integer sumTeamCommission = attendanceMonthlyDOList.stream().map(AttendanceMonthlyDO::getTeamCommission).reduce(0, Integer::sum);
        Integer sumBusinessCommission = attendanceMonthlyDOList.stream().map(AttendanceMonthlyDO::getBusinessCommission).reduce(0, Integer::sum);
        Integer sumOvertimePay = attendanceMonthlyDOList.stream().map(AttendanceMonthlyDO::getOvertimePay).reduce(0, Integer::sum);
        Integer sumSubsidy = attendanceMonthlyDOList.stream().map(AttendanceMonthlyDO::getSubsidy).reduce(0, Integer::sum);
        Long empCost = Long.valueOf(taxBefore.intValue() + sumPfDed + sumPfDed + sumTeamCommission + sumBusinessCommission + sumOvertimePay + sumSubsidy);

        //五险一金
        Long empSocPf = Long.valueOf(sumSocDed + sumPfDed);

        //按年月保存归档记录
        AttendanceMonthlyArchiveAddDTO attendanceMonthlyArchiveAddDTO = new AttendanceMonthlyArchiveAddDTO();
        attendanceMonthlyArchiveAddDTO.setCompanyId(attendanceMonthlyAddDTO.getCompanyId());
        attendanceMonthlyArchiveAddDTO.setYear(attendanceMonthlyAddDTO.getYear());
        attendanceMonthlyArchiveAddDTO.setMonth(attendanceMonthlyAddDTO.getMonth());
        attendanceMonthlyArchiveAddDTO.setStatus(1);
        attendanceMonthlyArchiveAddDTO.setEmpCost(empCost);
        attendanceMonthlyArchiveAddDTO.setEmpSocPf(empSocPf);
        attendanceMonthlyArchiveAddDTO.setEmpTaxBefore(taxBefore);
        return save(attendanceMonthlyArchiveAddDTO, tokenUser);
    }
}




